// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf


// The little endian format is the default for mgc files.  This is the format
// for the PC.  For platforms that use big endian format, you need to define
// MGC_BIG_ENDIAN.  For swapping to big endian format, native types assumed
// to be 1, 2, 4, or 8 bytes.  This assumption might not be valid on
// architectures with word size larger than 32-bits.

//----------------------------------------------------------------------------
inline FILE* MgcStream::GetFile ()
{
    return m_pkFile;
}
//----------------------------------------------------------------------------
template <class T>
void MgcStreamRead (MgcStream& rkStream, T& rtValue)
{
    fread(&rtValue,sizeof(T),1,rkStream.GetFile());

#ifdef MGC_BIG_ENDIAN
    if ( sizeof(T) > 1 )
    {
        char* acBytes = (char*) &rtValue;
        char cSave;

        switch ( sizeof(T) )
        {
        case 2:
            cSave = acBytes[0];
            acBytes[0] = acBytes[1];
            acBytes[1] = cSave;
            break;
        case 4:
            cSave = acBytes[0];
            acBytes[0] = acBytes[3];
            acBytes[3] = cSave;
            cSave = acBytes[1];
            acBytes[1] = acBytes[2];
            acBytes[2] = cSave;
            break;
        case 8:
            cSave = acBytes[0];
            acBytes[0] = acBytes[7];
            acBytes[7] = cSave;
            cSave = acBytes[1];
            acBytes[1] = acBytes[6];
            acBytes[6] = cSave;
            cSave = acBytes[2];
            acBytes[2] = acBytes[5];
            acBytes[5] = cSave;
            cSave = acBytes[3];
            acBytes[3] = acBytes[4];
            acBytes[4] = cSave;
            break;
        default:
            assert( false );
        }
    }
#endif
}
//---------------------------------------------------------------------------
template <class T>
void MgcStreamRead (MgcStream& rkStream, T* ptValue, unsigned int uiQuantity)
{
    fread(ptValue,sizeof(T),uiQuantity,rkStream.GetFile());

#ifdef MGC_BIG_ENDIAN
    if ( sizeof(T) > 1 )
    {
        for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
        {
            char* acBytes = (char*) &ptValue[uiI];
            char cSave;

            switch ( sizeof(T) )
            {
            case 2:
                cSave = acBytes[0];
                acBytes[0] = acBytes[1];
                acBytes[1] = cSave;
                break;
            case 4:
                cSave = acBytes[0];
                acBytes[0] = acBytes[3];
                acBytes[3] = cSave;
                cSave = acBytes[1];
                acBytes[1] = acBytes[2];
                acBytes[2] = cSave;
                break;
            case 8:
                cSave = acBytes[0];
                acBytes[0] = acBytes[7];
                acBytes[7] = cSave;
                cSave = acBytes[1];
                acBytes[1] = acBytes[6];
                acBytes[6] = cSave;
                cSave = acBytes[2];
                acBytes[2] = acBytes[5];
                acBytes[5] = cSave;
                cSave = acBytes[3];
                acBytes[3] = acBytes[4];
                acBytes[4] = cSave;
                break;
            default:
                assert( false );
            }
        }
    }
#endif
}
//---------------------------------------------------------------------------
template <class T>
void MgcStreamWrite (MgcStream& rkStream, const T& rtValue)
{
#ifdef MGC_BIG_ENDIAN
    if ( sizeof(T) > 1 )
    {
        T tTmpValue = rtValue;
        char* acBytes = (char*) &tTmpValue;
        char cSave;

        switch ( sizeof(T) )
        {
        case 2:
            cSave = acBytes[0];
            acBytes[0] = acBytes[1];
            acBytes[1] = cSave;
            break;
        case 4:
            cSave = acBytes[0];
            acBytes[0] = acBytes[3];
            acBytes[3] = cSave;
            cSave = acBytes[1];
            acBytes[1] = acBytes[2];
            acBytes[2] = cSave;
            break;
        case 8:
            cSave = acBytes[0];
            acBytes[0] = acBytes[7];
            acBytes[7] = cSave;
            cSave = acBytes[1];
            acBytes[1] = acBytes[6];
            acBytes[6] = cSave;
            cSave = acBytes[2];
            acBytes[2] = acBytes[5];
            acBytes[5] = cSave;
            cSave = acBytes[3];
            acBytes[3] = acBytes[4];
            acBytes[4] = cSave;
            break;
        default:
            assert( false );
        }

        fwrite(&tTmpValue,sizeof(T),1,rkStream.GetFile());
    }
    else
    {
        fwrite(&rtValue,sizeof(T),1,rkStream.GetFile());
    }
#else
    fwrite(&rtValue,sizeof(T),1,rkStream.GetFile());
#endif
}
//---------------------------------------------------------------------------
template <class T>
void MgcStreamWrite (MgcStream& rkStream, const T* ptValue,
    unsigned int uiQuantity)
{
#ifdef MGC_BIG_ENDIAN
    if ( sizeof(T) > 1 )
    {
        T* ptTmpValue = new T[uiQuantity];
        memcpy(ptTmpValue,ptValue,uiQuantity*sizeof(T));
        for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
        {
            char* acBytes = (char*) ptTmpValue[uiI];
            char cSave;

            switch ( sizeof(T) )
            {
            case 2:
                cSave = acBytes[0];
                acBytes[0] = acBytes[1];
                acBytes[1] = cSave;
                break;
            case 4:
                cSave = acBytes[0];
                acBytes[0] = acBytes[3];
                acBytes[3] = cSave;
                cSave = acBytes[1];
                acBytes[1] = acBytes[2];
                acBytes[2] = cSave;
                break;
            case 8:
                cSave = acBytes[0];
                acBytes[0] = acBytes[7];
                acBytes[7] = cSave;
                cSave = acBytes[1];
                acBytes[1] = acBytes[6];
                acBytes[6] = cSave;
                cSave = acBytes[2];
                acBytes[2] = acBytes[5];
                acBytes[5] = cSave;
                cSave = acBytes[3];
                acBytes[3] = acBytes[4];
                acBytes[4] = cSave;
                break;
            default:
                assert( sizeof(T) == 1 );
            }
        }

        fwrite(ptTmpValue,sizeof(T),uiQuantity,rkStream.GetFile());
        delete[] ptTmpValue;
    }
    else
    {
        fwrite(ptValue,sizeof(T),uiQuantity,rkStream.GetFile());
    }
#else
    fwrite(ptValue,sizeof(T),uiQuantity,rkStream.GetFile());
#endif
}
//----------------------------------------------------------------------------
